/**
 * Copyright (C),2011-2012,北京国电通网络技术有限公司.
 * FileName:	server.cpp
 * Author:		LiuHaifeng
 * Version:		V0.1
 * Date:		2011-11-15
 * Description	This file receives data from webservice, and put them in share memory for dispose
 */
/**
 * History:
 * 		Author		date		Version		Description
 */

#include <fcntl.h>				///open()/close()
#include <sys/mman.h>			///shared memory relative
#include <semaphore.h>			///sem_t and relative
#include "global.h"
///以下头文件必须包含
#include "../server/soapCCwebService.h"
#include "../server/CCweb.nsmap"

///private function
static int serverInit();
static char g_noResRet[]="#ffffffffff#ff#ffff#ff#";

///global variable
int g_fd;					///file descriptor of shared memory
char* g_addr;				///started address of shared memory
sem_t g_sem;				///semaphore protect shared memory


int main(int argc,char *argv[])
{
	PRINTOUT("%s","in serverMain");
	///initialization
	if(-1==serverInit())
		return -1;
	///声明服务器端类
	CCwebService webserver;
	///运行简单框架程序
	if (webserver.run(PORT))
	{
		///clear resource
		munmap(g_addr,SHARESIZE);
		close(g_fd);
		///run  iterative  server  on  port  until  fatal error
		//webserver.soap_stream_fault(std::cerr); //delete by charlie
		
		return SOAP_ERR;
	}
	///exit and clear resource
	///unmap shared memory.
	munmap(g_addr,SHARESIZE);
	//system("ipcs -m");	///see something relative to shared memory.
	close(g_fd);
	PRINTOUT("%s","out seADDSOCKETrverMain");
	return 0;
}
///重写命令处理函数
/***
 * 		name:	 	CCwebService::comWithoutResult()
 * 		function:	command dispose and without result
 *      param:   	input:char *cmd, output:struct result *result
 *      variable:
 *		retval:     return command result from control
 *		author/date:liuhaifeng/2011.11.10
 *      Version:    0.0.1
 *
 ****/
int CCwebService::comWithoutResult(char *cmd, struct result *result)
{
	PRINTOUT("%s","in comWithoutResult");
	int l_temp=0;
	BEGIN:
	while(!isClear())       ///
	{
		myDelay(1);
	}
	sem_wait(&g_sem);///!!!!!
	setFlagNo();
	if(!haveRES())
	{
		sem_post(&g_sem);///!!!!!
		goto BEGIN;
	}
	myDelay(5);
	l_temp=strlen(cmd);
	memcpy(&g_addr[1],cmd,l_temp);
	g_addr[l_temp+1]=0;
	setCMDFlag();                                            ///get cmd flag;
	sem_post(&g_sem);///!!!!!
	PRINTOUT("%s","out comWithoutResult");
	///clear flag
	//clearFlag();											///done in 'SmartHome-VER3-main'
	return SOAP_OK;
}
///重写命令处理函数
/***
 * 		name:	 	CCwebService::comWithoutResult()
 * 		function:	command dispose and without result
 *      param:   	input:char *cmd, output:struct result *result
 *      variable:
 *		retval:     return command result from control
 *		author/date:liuhaifeng/2011.11.10
 *      Version:    0.0.1
 *
 ****/
int CCwebService::comWithResult(char *cmd, char **result)
{
	PRINTOUT("%s","in comWithResult");
	int l_temp=0;
	BEGIN:
	while(!isClear())
	{
		;
	}
	sem_wait(&g_sem);///!!!!!
	setFlag();
	if(!haveRES())
	{
		sem_post(&g_sem);///!!!!!
		goto BEGIN;
	}
	myDelay(5);								///如果在webservice读取共享内存数据时，命令拷贝到共享内存会出现数据紊乱
	l_temp=strlen(cmd);
	memcpy(&g_addr[1],cmd,l_temp);
	g_addr[l_temp+1]=0;
	setCMDFlag(); 								///get cmd flag;
	///wait result
	l_temp=0;
	while(!isResult())
	{
		myDelay(5);
		///???bug???time out judge
		if(l_temp++>WAITRES)
		{
			*result=g_noResRet;
			clearFlag();
			sem_post(&g_sem);///!!!!!
			return SOAP_OK;
		}
	}
	///return result
	*result=&g_addr[1];
	///clear flag
	clearFlag();
	sem_post(&g_sem);///!!!!!

	PRINTOUT("%s","out comWithResult");
	return SOAP_OK;
}
/***serverInit() brief initialization function
 * param void
 *
 * retval int,0 if successfully -1 if failed
 ***/
static int serverInit()
{
	///open a file used as shared memory.
	g_fd=open(SHARENAME,O_CREAT|O_RDWR,0777);
	if(-1==g_fd)
	{
		ERROROUT("open file failed!");
		return -1;
	}
	///share memory.---return void*
	g_addr=(char*)mmap( NULL,SHARESIZE,PROT_READ|PROT_WRITE,MAP_SHARED,g_fd,0 );
	if (MAP_FAILED==g_addr)
	{
		ERROROUT("mmap failed!");
		return -1;
	}
	///can be used by only one process(magic 0),and initial value is 1
	if(-1==sem_init(&g_sem,0,1))
	{
		ERROROUT("g_sem init failed!");
		return -1;
	}
	return 0;
}
/***myDelay() brief implement delay function.
 *	param 	delay[in], 'ms' to delay.
 *
 *	retval  void, null
 ***/
void myDelay(int delay)
{
	if(delay<=0)
		return;
	struct timeval timeout;
	timeout.tv_sec=delay/1000;
	timeout.tv_usec=(delay%1000)*1000;			///ms
	select(0,NULL,NULL,NULL,&timeout);
}
